//
//  HTTPManager.swift
//  fir-mac
//
//  Created by isaced on 2017/5/8.
//
//

import Foundation
import Alamofire
import Alamofire_SwiftyJSON
import SwiftyJSON
import KeychainAccess


enum UploadAppType: String {
    case ios = "ios"
    case android = "android"
}

class HTTPManager {
    
    static let shared = HTTPManager()

    var isFirOrPGY: Bool? = {
        guard let str = Keychain(service: KeychainFirmacServiceName)[KeychainFirmacTokenType] else {
            return nil
        }
        return (str == TokenType.fir.rawValue)
    }()
    
    var APIToken: String? = {
        return Keychain(service: KeychainFirmacServiceName)[KeychainFirmacAPITokenKey]
    }()
    
    var uploading: Bool = false
    
    func fetchApps(callback: @escaping ((_ apps: [FIRApp])->Void)) {
        guard let APIToken = APIToken else {
            callback([])
            return
        }
        
        Alamofire.request("http://api.bq04.com/apps", parameters: ["api_token": APIToken]).responseSwiftyJSON { (response) in
            var apps: [FIRApp] = []
            if let items = response.value?["items"].array {
                for item in items {
                    let app = FIRApp(json: item)
                    apps.append(app)
                }
            }
            callback(apps)
        }
    }
    
    func fatchAppDetail(app: FIRApp, callback: @escaping (()->Void)) {
        guard let APIToken = APIToken else {
            callback()
            return
        }
        
        Alamofire.request("http://api.bq04.com/apps/\(app.ID)", method: .get, parameters: ["api_token": APIToken]).responseSwiftyJSON { (response) in
            app.fillDetail(with: response.value)
            callback()
        }
    }
    
    private func prepareUploadApp(bundleID: String, isFir: Bool, type:UploadAppType, callback:@escaping ((JSON?)->Void)) {
        guard let APIToken = APIToken else {
            callback(nil)
            return
        }
        
        if isFir {
            Alamofire.request("http://api.bq04.com/apps", method: .post, parameters: ["api_token": APIToken, "bundle_id":bundleID,"type": type.rawValue]).responseSwiftyJSON { (response) in
                callback(response.value)
            }
        } else {
            Alamofire.request("https://www.pgyer.com/apiv2/app/getCOSToken", method: .post, parameters: ["_api_key": APIToken, "buildType":"ios"]).responseSwiftyJSON { (response) in
                callback(response.value)
            }
        }
    }
    
    private func firUploadFile(uploadUrl: String,
                    qiniuKey: String,
                    qiniuToken: String,
                    prefix: String,
                    file: Data?,
                    fileURL: URL?,
                    appName: String? = nil,
                    version: String? = nil,
                    build: String? = nil,
                    iosReleaseType: String? = nil,
                    changeLog:String? = nil,
                    encodingRequestSuccess: ((UploadRequest)->Void)? = nil,
                    uploadProgress: Request.ProgressHandler?,
                    complate: @escaping ((_ success: Bool)->Void)) {
        Alamofire.upload(multipartFormData: { (multipartFormData) in
            multipartFormData.append(qiniuKey.data(using: .utf8)!, withName: "key")
            multipartFormData.append(qiniuToken.data(using: .utf8)!, withName: "token")
            if let file = file {
                multipartFormData.append(file, withName: "file")
            }
            if let fileURL = fileURL {
                multipartFormData.append(fileURL, withName: "file")
            }
            if let appName = appName {
                multipartFormData.append(appName.data(using: .utf8)!, withName: "\(prefix)name")
            }
            if let version = version {
                multipartFormData.append(version.data(using: .utf8)!, withName: "\(prefix)version")       // prefix + "version"
            }
            if let build = build {
                multipartFormData.append(build.data(using: .utf8)!, withName: "\(prefix)build")           // prefix + "build"
            }
            if let iosReleaseType = iosReleaseType {
                multipartFormData.append(iosReleaseType.data(using: .utf8)!, withName: "\(prefix)release_type")     // prefix + "release_type"
            }
            if let changeLog = changeLog {
                multipartFormData.append(changeLog.data(using: .utf8)!, withName: "\(prefix)changelog")
            }
            if let fileURL = fileURL {
                multipartFormData.append(fileURL, withName: "file")
            }
        }, to: uploadUrl) { (encodingResult) in
            switch encodingResult {
            case .success(let upload, _, _):
                
                encodingRequestSuccess?(upload)
                
                upload.uploadProgress(closure: { (progress) in
                    uploadProgress?(progress)
                })
                upload.responseJSON { response in
                    debugPrint(response)
                    complate(response.result.isSuccess)
                }
            case .failure(let encodingError):
                print(encodingError)
                complate(false)
            }
        }
    }
    
    /// fir上传
    func firUploadApp(appInfo: ParsedAppInfo,
                   encodingRequestSuccess: ((UploadRequest)->Void)? = nil,
                   uploadProgress: Request.ProgressHandler?,
                   complate: @escaping ((_ success: Bool, _ qrCodeStr: String?)->Void))
    {
        guard let bundleID = appInfo.bundleID,
            let appName = appInfo.appName,
            let version = appInfo.version,
            let build = appInfo.build,
            let type = appInfo.type,
            let souceFile = appInfo.sourceFileURL else {
            complate(false, nil)
            return
        }
        
        // flag uploading
        self.uploading = true
        
        prepareUploadApp(bundleID: bundleID, isFir: true, type: type) { (response) in
            
            //先拼接上传成功的短连接
            var shortUrlStr = ""
            if let domain = response?.dictionary?["download_domain"]?.string,
               let short = response?.dictionary?["short"]?.string{
                shortUrlStr = "http://" + domain + "/" + short
            }
            
            if let uploadFieldPrefix = response?.dictionary?["cert"]?["prefix"].string {
                //1.upload icon
                if  let iconQiniuKey = response?.dictionary?["cert"]?["icon"]["key"].string,
                    let iconQiniuToken = response?.dictionary?["cert"]?["icon"]["token"].string,
                    let iconUploadUrl = response?.dictionary?["cert"]?["icon"]["upload_url"].url?.absoluteString
                {
                    self.firUploadFile(uploadUrl: iconUploadUrl,
                               qiniuKey: iconQiniuKey,
                               qiniuToken: iconQiniuToken,
                               prefix: uploadFieldPrefix,
                               file: nil,
                               fileURL: appInfo.iconUrl,
                               uploadProgress: nil, complate: { (success) in
                                if !success {
                                    print("icon upload error...")
                                }
                    })
                }
                
                //2.upload package
                if  let binaryQiniuKey = response?.dictionary?["cert"]?["binary"]["key"].string,
                    let binaryQiniuToken = response?.dictionary?["cert"]?["binary"]["token"].string,
                    let binaryUploadUrl = response?.dictionary?["cert"]?["binary"]["upload_url"].url?.absoluteString
                {
                    
                    self.firUploadFile(uploadUrl: binaryUploadUrl,
                                    qiniuKey: binaryQiniuKey,
                                    qiniuToken: binaryQiniuToken,
                                    prefix: uploadFieldPrefix,
                                    file: nil,
                                    fileURL: souceFile,
                                    appName: appName,
                                    version: version,
                                    build: build,
                                    iosReleaseType: appInfo.iosReleaseType?.rawValue,
                                    encodingRequestSuccess: encodingRequestSuccess,
                                    uploadProgress: { (p) in
                                        uploadProgress?(p)
                    }, complate: { (success) in
                        complate(success, shortUrlStr)
                        
                        if success {
                            if let url = URL(string: shortUrlStr) {
                                NSWorkspace.shared.open(url)
                                
                                //删除上传的url
                                try? FileManager.default.removeItem(at: souceFile)
                                var ipaFolder = souceFile.path
                                ipaFolder.removeLast(4)
                                try? FileManager.default.removeItem(atPath: ipaFolder)
                            }
                        } else {
                            print("❤️❤️❤️❤️❤️上传ipa失败")
                        }
                        // flag uploading
                        self.uploading = false
                    })
                }
            } else {
                complate(false, nil)
            }
        }
    }
    
    /// 蒲公英上传
    func pgyUploadApp(appInfo: ParsedAppInfo,
                      encodingRequestSuccess: ((UploadRequest)->Void)? = nil,
                      uploadProgress: Request.ProgressHandler?,
                      complate: @escaping ((_ success: Bool, _ qrCodeStr: String?)->Void)) {
        
        
        guard let bundleID = appInfo.bundleID,
            let type = appInfo.type,
            let sourceFile = appInfo.sourceFileURL else {
            complate(false, nil)
            return
        }
        
        // flag uploading
        self.uploading = true
        
        prepareUploadApp(bundleID: bundleID, isFir: false, type: type) { [weak self] (response) in
            
            if let key = response?.dictionary?["data"]?["key"].string,
               let signature = response?.dictionary?["data"]?["params"]["signature"].string,
               let uploadToken = response?.dictionary?["data"]?["params"]["x-cos-security-token"].string,
               let urlStr = response?.dictionary?["data"]?["endpoint"].string {
                
                self?.pgyUploadFile(uploadUrl: urlStr, key: key, pgyToken: uploadToken, signature: signature, fileURL: sourceFile) { progress in
                    
                    uploadProgress?(progress)
                } complate: { [weak self] (success) in
                    
                    guard let self = self else {
                        complate(false, nil)
                        return
                    }
                    if success {
                        
                        self.pgyVerifyIpa(buildKey: key, sourceFile: sourceFile, complate: complate)
                        
                    } else {
                        print("❤️❤️❤️❤️❤️上传ipa失败")
                        complate(false, nil)
                    }
                    // flag uploading
                    self.uploading = false
                }

            }
        }
    }
    
    /// 验证蒲公英是否上传成功
    private func pgyVerifyIpa(buildKey: String,
                              sourceFile: URL,
                              complate: @escaping ((_ success: Bool, _ qrCodeStr: String?)->Void)) {
        DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
            //网络请求是否发布完成
            Alamofire.request("https://www.pgyer.com/apiv2/app/buildInfo", method: .post, parameters: ["_api_key": self.APIToken!, "buildKey": buildKey]).responseSwiftyJSON { [weak self] (response) in
                
                print("成功上传的json----❤️\(String(describing: response.value?.dictionary))")
                guard let code = response.value?.dictionary?["code"]?.int,
                      let self = self else {
                    complate(false, nil)
                    return
                }
                switch code {
                case 0://成功
                    let qrCode = "https://www.pgyer.com/" + (response.value?.dictionary?["data"]?["buildShortcutUrl"].string ?? "")
                    complate(true, qrCode)
                    self.uploadSuccessHandle(openUrlStr: qrCode, trashUrl: sourceFile)
                case 1246://还在上传
                    self.pgyVerifyIpa(buildKey: buildKey, sourceFile: sourceFile, complate: complate)
                default://上传失败
                    complate(false, nil)
                    self.uploadSuccessHandle(openUrlStr: "https://www.pgyer.com/manager/dashboard/app", trashUrl: sourceFile)
                }
            }
        }
    }
    
    private func pgyUploadFile(uploadUrl: String,
                               key: String,
                               pgyToken: String,
                               signature: String,
                               fileURL: URL,
                               encodingRequestSuccess: ((UploadRequest)->Void)? = nil,
                               uploadProgress: Request.ProgressHandler?,
                               complate: @escaping ((_ success: Bool)->Void)) {
        Alamofire.upload(multipartFormData: { (multipartFormData) in
            multipartFormData.append(key.data(using: .utf8)!, withName: "key")
            multipartFormData.append(pgyToken.data(using: .utf8)!, withName: "x-cos-security-token")
            multipartFormData.append(signature.data(using: .utf8)!, withName: "signature")
            multipartFormData.append(fileURL, withName: "file")
        }, to: uploadUrl) { (encodingResult) in
            switch encodingResult {
            case .success(let upload, _, _):
                
                encodingRequestSuccess?(upload)
                
                upload.uploadProgress(closure: { (progress) in
                    uploadProgress?(progress)
                })
                upload.responseJSON { response in
                    debugPrint(response)
                    complate(response.result.isSuccess)
                }
            case .failure(let encodingError):
                print(encodingError)
                complate(false)
            }
        }
    }
    
    /// 上传成功后干的事，打开网页，删除垃圾
    private func uploadSuccessHandle(openUrlStr: String, trashUrl: URL) {
        NSWorkspace.shared.open(URL(string: openUrlStr)!)
        //删除上传的url
        try? FileManager.default.removeItem(at: trashUrl)
        var ipaFolder = trashUrl.path
        ipaFolder.removeLast(4)
        try? FileManager.default.removeItem(atPath: ipaFolder)
    }
}
